/** \file osocklib/ftal.h
 * \brief File Transfert Abstraction Layer
 * \author Jean Loup Le Roux <nc@nightmare-creature.org>
 *  
 * This is a additional layer above osocklib, used to handle ressource
 * transferts between nodes (hosts). This is not a general purpose module, as it
 * has been designed specificaly for YOP (http://code.google.com/p/yopp2p/).
 */

#ifndef FTAL_H
#define FTAL_H

#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#include "../global.h"
#include "../rsrcmanager/rsrcmanager.h"
#include "../sharedmemory/sharedmemory.h"
#include "../osocklib/osocklib.h"


/** \brief Complete Host Structure 
 * This is an encapsulation of everything needed by FTAL to
 * define a network node (or host).
 */
typedef struct _chost_s {
  /// IPv4 address in numbers-and-dots format 
  char ipv4[16]; 
  /// port of remote host, should not go below 1024
  in_port_t port;
  /// protocol to use, either TCP or UDP
  protocol_t proto;
} chost_s;

/** \brief UDP Header structure 
 *  This header in concatenated at the beginning of every network packet handled in UDP mode. Its
 *  values change for every new packet, describing the status of
 *  the sending/receiving process. It should be checked every time we can.
 *  \note Actual total size of the header: 4*64+64+64 = 384 bits = 48 bytes.
 *  This may vary in the future.
 *  \todo Use more #defines to set sizes.
 */
typedef struct _udp_header_s {
  /// Unique file key (32bytes, 256 bits), so far file_key_t is an ASCII string of 
  // 32 * 8 = 256bits + '\0' at the end
  int64_t key[3];
  /// Absolute begin offset of network packet (8 bytes, 64 bits)
  int64_t npacket_begin;
  /// Absolute end offset of network packet (8 bytes, 64 bits)
  int64_t npacket_end;
} udp_header_s;


/** \brief SM TX report from FTAL
 * General info about FTAL child status during partial resource sending
 */
typedef struct _ftal_tx_report {
  /// End sending offset
  off_t end;
  /// Current sending offset
  off_t current_tx_offset;
  /// Average sending speed in bytes per second
  float tx_speed;

} ftal_tx_report;


/** \brief SM RX report from FTAL
 * General info about FTAL child status during partial resource receiving
 */
typedef struct _ftal_rx_report {
  /// End receiving offset
  off_t end;
  /// Current receiving offset
  off_t current_rx_offset;
  /// Average receiving speed in bytes per second
  float rx_speed;
  /// Last valid range
  range_s valid_range; 

} ftal_rx_report;


/** \brief Compute an outgoing UDP header structure
 * One must call this function to set the new header every time we send a new
 * network packet in UDP mode. Then, one must concatenate this header at the
 * beginning of the network packet.
 * \param header Header structure to fill
 * \param ascii_key Unique file key provided by the calling program
 * \param npacket_begin Absolute beginning offset provided by FTAL_sendrsrc()
 * \param npacket_end Absolute ending offset provided by FTAL_sendrsrc()
 * \return 0 (success) or -1
 */
int FTAL_out_udp_header( udp_header_s* header, 
                          const filekey_t ascii_key, 
                          const off_t npacket_begin, 
                          const off_t npacket_end );


/** \brief Compute an incoming UDP header structure
 * One must call this function to extract the udp header from a network packet 
 * every time we receive a new network packet in UDP mode. 
 * \param header Header structure to fill
 * \param datap Pointer to network packet data zone
 * \return 0 (success) or -1
 */
int FTAL_in_udp_header( udp_header_s* header, const void* datap );


/** \brief Sends a local ressource to a remote host
 * \param localR localResource pointer
 * \param start First block of the read range
 * \param end Last block of the read range
 * \param host IP, PORT and PROTOCOL
 * \param SM Shared Memory element used to transmit tx_speed, current_tx_offset
 * and end to Father
 * \return 0 (success) or -1
 * \todo Prevent FTAL_sendrsrc() to enter an infinite loop if RMC_read()
 * always returns 0 (NULL data pointer for example).
 * \todo Manage endianess issues (architecture dependent)
 */
int FTAL_sendrsrc( localResource_s* localR,
                   off_t start,
                   off_t end, 
                   const chost_s host,
                   SM_elem_s* SM);


/** \brief Receives a local ressource from a remote host
 * \param localR localResource pointer
 * \param start First block of the write range
 * \param end Last block of the write range
 * \param host IP, PORT and PROTOCOL
 * \param SM Shared Memory element used to transmit rx_speed, current_rx_offset,
 * end and valid_range to Father
 * \return 0 (success) or -1
 * \todo Manage endianess issues (architecture dependent)
*/
int FTAL_recvrsrc( localResource_s* localR,
                   off_t start,
                   off_t end, 
                   const chost_s host,
                   SM_elem_s* SM);

#endif 

/* end of ftal.h */

